/*
 * Copyright (c) 2022 Hong Jiahua
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
#include <stdio.h>
#include <string.h>

#include "jh_static_list.h"
/************************************************************************/
/*                                                                      */
/************************************************************************/
//遍历链表示例
void static_list_for_each_test(void)
{
    int i;
    int cursor;
    int next_cursor;
    itemtype value;
    itemtype *p_value;
    
    //定义链表
    jh_static_list_buf list_buf;
    
    //初始化
    jh_static_list_buf_init(list_buf);
    
    printf("********************************\n");
    printf("遍历链表 示例\n");
    printf("********************************\n");
    
    //放入数值
    for (i = 0; i < 10; i++)
    {
        value = i + 10;
        //往链表尾添加数据
        JH_STATIC_LIST_ADD_TAIL_TYPE(list_buf, data, value);
        printf("Node %d has added to the list...\n", i);
    }
    printf("\n");
    
    printf("********************************\n");
    printf("遍历链表 方式一\n");
    printf("********************************\n");
    i = 0;
    JH_STATIC_LIST_FOR_EACH(cursor, list_buf)
    {
        printf("Node %d's data: %d\n", i, list_buf[cursor].data);
        i++;
    }
    printf("\n");
    
    printf("********************************\n");
    printf("遍历链表 方式二\n");
    printf("********************************\n");
    i = 0;
    JH_STATIC_LIST_FOR_EACH_SAFE(cursor, next_cursor, list_buf)
    {
        printf("Node %d's data: %d\n", i, list_buf[cursor].data);
        i++;
    }
    printf("\n");
    
    printf("********************************\n");
    printf("遍历链表 方式三\n");
    printf("********************************\n");
    i = 0;
    JH_STATIC_LIST_FOR_EACH_ENTRY_ELEMENT(cursor, list_buf, p_value, data)
    {
        printf("Node %d's data: %d\n", i, *p_value);
        i++;
    }
    printf("\n");
    
    printf("********************************\n");
    printf("遍历链表 方式四\n");
    printf("********************************\n");
    i = 0;
    JH_STATIC_LIST_FOR_EACH_ENTRY_ELEMENT_SAFE(cursor, next_cursor, list_buf, p_value, data)
    {
        printf("Node %d's data: %d\n", i, *p_value);
        i++;
    }
    printf("\n");
}

//反向遍历链表示例
void static_list_for_each_reverse_test(void)
{
    int i;
    int cursor;
    int next_cursor;
    itemtype value;
    itemtype *p_value;
    
    //定义链表
    jh_static_list_buf list_buf;
    
    //初始化
    jh_static_list_buf_init(list_buf);
    
    printf("********************************\n");
    printf("反向遍历链表 示例\n");
    printf("********************************\n");
    
    //放入数值
    for (i = 0; i < 10; i++)
    {
        value = i + 10;
        //往链表尾添加数据
        JH_STATIC_LIST_ADD_TAIL_TYPE(list_buf, data, value);
        printf("Node %d has added to the list...\n", i);
    }
    printf("\n");
    
    printf("********************************\n");
    printf("反向遍历链表 方式一\n");
    printf("********************************\n");
    i = 0;
    JH_STATIC_LIST_FOR_EACH_REVERSE(cursor, list_buf)
    {
        printf("Node %d's data: %d\n", i, list_buf[cursor].data);
        i++;
    }
    printf("\n");
    
    printf("********************************\n");
    printf("反向遍历链表 方式二\n");
    printf("********************************\n");
    i = 0;
    JH_STATIC_LIST_FOR_EACH_SAFE_REVERSE(cursor, next_cursor, list_buf)
    {
        printf("Node %d's data: %d\n", i, list_buf[cursor].data);
        i++;
    }
    printf("\n");
    
    printf("********************************\n");
    printf("反向遍历链表 方式三\n");
    printf("********************************\n");
    i = 0;
    JH_STATIC_LIST_FOR_EACH_ENTRY_ELEMENT_REVERSE(cursor, list_buf, p_value, data)
    {
        printf("Node %d's data: %d\n", i, *p_value);
        i++;
    }
    printf("\n");
    
    printf("********************************\n");
    printf("反向遍历链表 方式四\n");
    printf("********************************\n");
    i = 0;
    JH_STATIC_LIST_FOR_EACH_ENTRY_ELEMENT_SAFE_REVERSE(cursor, next_cursor, list_buf, p_value, data)
    {
        printf("Node %d's data: %d\n", i, *p_value);
        i++;
    }
    printf("\n");
}

//链表添加数据与删除数据示例
//往链表尾添加与删除数据
void static_list_add_and_delete_tail_test(void)
{
    int i;
    int cursor;
    itemtype value;
    itemtype *p_value;
    
    //定义链表
    jh_static_list_buf list_buf;
    
    //初始化
    jh_static_list_buf_init(list_buf);
    
    printf("********************************\n");
    printf("链表尾添加数据\n");
    printf("********************************\n");
    //放入数值
    for (i = 0; i < 10; i++)
    {
        value = i + 10;
        //往链表尾添加数据
        JH_STATIC_LIST_ADD_TAIL_TYPE(list_buf, data, value);
        printf("Node %d has added to the list...\n", i);
    }
    printf("\n");
    
    //判断链表是否为空
    printf("list %s empty\n", jh_static_list_is_empty(list_buf) ? "is" : "isn't");
    printf("\n");
    
    printf("********************************\n");
    printf("链表尾删除数据\n");
    printf("********************************\n");
    //删除数据数值
    for (i = 0; i < 10; i++)
    {
        //往链表尾删除数据
        JH_STATIC_LIST_REMOVE_TAIL_TYPE(list_buf, itemtype, data);
        printf("Node %d has del to the list...\n", i);
    }
    printf("\n");
    
    //判断链表是否为空
    printf("list %s empty\n", jh_static_list_is_empty(list_buf) ? "is" : "isn't");
    printf("\n");
    
    //遍历检查下链表
    i = 0;
    JH_STATIC_LIST_FOR_EACH_ENTRY_ELEMENT(cursor, list_buf, p_value, data)
    {
        printf("Node %d's data: %d\n", i, *p_value);
        i++;
    }
    printf("\n");
}

//往链表头添加与删除数据
void static_list_add_and_delete_head_test(void)
{
    int i;
    int cursor;
    itemtype value;
    itemtype *p_value;
    
    //定义链表
    jh_static_list_buf list_buf;
    
    //初始化
    jh_static_list_buf_init(list_buf);
    
    printf("********************************\n");
    printf("链表头添加数据\n");
    printf("********************************\n");
    //放入数值
    for (i = 0; i < 10; i++)
    {
        value = i + 10;
        //往链表头添加数据
        JH_STATIC_LIST_ADD_HEAD_TYPE(list_buf, data, value);
        printf("Node %d has added to the list...\n", i);
    }
    printf("\n");
    
    //遍历检查下链表
    i = 0;
    JH_STATIC_LIST_FOR_EACH_ENTRY_ELEMENT(cursor, list_buf, p_value, data)
    {
        printf("Node %d's data: %d\n", i, *p_value);
        i++;
    }
    printf("\n");
    
    //判断链表是否为空
    printf("list %s empty\n", jh_static_list_is_empty(list_buf) ? "is" : "isn't");
    printf("\n");
    
    printf("********************************\n");
    printf("链表头删除数据\n");
    printf("********************************\n");
    //删除数据数值
    for (i = 0; i < 10; i++)
    {
        //往链表头删除数据
        JH_STATIC_LIST_REMOVE_HEAD_TYPE(list_buf, itemtype, data);
        printf("Node %d has del to the list...\n", i);
    }
    printf("\n");
    
    //判断链表是否为空
    printf("list %s empty\n", jh_static_list_is_empty(list_buf) ? "is" : "isn't");
    printf("\n");
    
    //遍历检查下链表
    i = 0;
    JH_STATIC_LIST_FOR_EACH_ENTRY_ELEMENT(cursor, list_buf, p_value, data)
    {
        printf("Node %d's data: %d\n", i, *p_value);
        i++;
    }
    printf("\n");
}

//获取链表头的数据并删除释放结点
void static_list_safe_delete_head_test(void)
{
    int i;
    itemtype value;
    
    //定义链表
    jh_static_list_buf list_buf;
    
    //初始化
    jh_static_list_buf_init(list_buf);
    
    printf("********************************\n");
    printf("获取链表头的数据并删除释放结点\n");
    printf("********************************\n");
    
    //放入数值
    for (i = 0; i < 10; i++)
    {
        value = i + 10;
        //往链表尾添加数据
        JH_STATIC_LIST_ADD_TAIL_TYPE(list_buf, data, value);
        printf("Node %d has added to the list...\n", i);
    }
    printf("\n");
    
    //链表头安全删除数据
    for (i = 0; i < 10; i++)
    {
        if(JH_STATIC_LIST_REMOVE_HEAD_TYPE_SAFE(list_buf, data, value))
            printf("Node %d has %d...\n", i, value);
    }
    
    //判断链表是否为空
    printf("list %s empty\n", jh_static_list_is_empty(list_buf) ? "is" : "isn't");
    printf("\n");
}

//获取链表尾的数据并删除释放结点
void static_list_safe_delete_tail_test(void)
{
    int i;
    itemtype value;
    
    //定义链表
    jh_static_list_buf list_buf;
    
    //初始化
    jh_static_list_buf_init(list_buf);
    
    printf("********************************\n");
    printf("获取链表尾的数据并删除释放结点\n");
    printf("********************************\n");
    
    //放入数值
    for (i = 0; i < 10; i++)
    {
        value = i + 10;
        //往链表尾添加数据
        JH_STATIC_LIST_ADD_TAIL_TYPE(list_buf, data, value);
        printf("Node %d has added to the list...\n", i);
    }
    printf("\n");
    
    //链表尾安全删除数据
    for (i = 0; i < 10; i++)
    {
        if(JH_STATIC_LIST_REMOVE_TAIL_TYPE_SAFE(list_buf, data, value))
            printf("Node %d has %d...\n", i, value);
    }
    
    //判断链表是否为空
    printf("list %s empty\n", jh_static_list_is_empty(list_buf) ? "is" : "isn't");
    printf("\n");
}

//查看链表头和尾的数据
void static_list_peek_test(void)
{
    int i;
    itemtype value;
    itemtype *p_value;
    
    //定义链表
    jh_static_list_buf list_buf;
    
    //初始化
    jh_static_list_buf_init(list_buf);
    
    printf("********************************\n");
    printf("查看链表头和尾的数据\n");
    printf("********************************\n");
    
    //放入数值
    for (i = 0; i < 10; i++)
    {
        value = i + 10;
        //往链表尾添加数据
        JH_STATIC_LIST_ADD_TAIL_TYPE(list_buf, data, value);
        printf("Node %d has added to the list...\n", i);
    }
    printf("\n");
    
    //查看链表头的数据
    p_value = JH_STATIC_LIST_PEEK_HEAD_TYPE(list_buf, itemtype, data);
    printf("Node HEAD has %d...\n", *p_value);
    
    //查看链表尾的数据
    p_value = JH_STATIC_LIST_PEEK_TAIL_TYPE(list_buf, itemtype, data);
    printf("Node TAIL has %d...\n", *p_value);
    
    printf("\n");
}

//清空所有数据
void static_list_clear_test(void)
{
    int i;
    int cursor;
    int next_cursor;
    itemtype value;
    itemtype *p_value;
    
    //定义链表
    jh_static_list_buf list_buf;
    
    //初始化
    jh_static_list_buf_init(list_buf);
    
    printf("********************************\n");
    printf("清空所有数据\n");
    printf("********************************\n");
    
    //放入数值
    for (i = 0; i < 10; i++)
    {
        value = i + 10;
        //往链表尾添加数据
        JH_STATIC_LIST_ADD_TAIL_TYPE(list_buf, data, value);
        printf("Node %d has added to the list...\n", i);
    }
    printf("\n");
    
    //清空所有数据
    JH_STATIC_LIST_FOR_EACH_ENTRY_ELEMENT_SAFE(cursor, next_cursor, list_buf, p_value, data) {
        printf("Node has %d...\n", *p_value);
        jh_static_list_delete_and_free(list_buf, cursor);
    }
    
    //判断链表是否为空
    printf("list %s empty\n", jh_static_list_is_empty(list_buf) ? "is" : "isn't");
    printf("\n");
}

//遍历链表中删除特定数据
void static_list_for_each_delete_test(void)
{
    int i;
    int cursor;
    int next_cursor;
    itemtype value;
    itemtype *p_value;
    
    //定义链表
    jh_static_list_buf list_buf;
    
    //初始化
    jh_static_list_buf_init(list_buf);
    
    printf("********************************\n");
    printf("遍历链表中删除特定数据\n");
    printf("********************************\n");
    
    //放入数值
    for (i = 0; i < 10; i++)
    {
        value = i + 10;
        //往链表尾添加数据
        JH_STATIC_LIST_ADD_TAIL_TYPE(list_buf, data, value);
        printf("Node %d has added to the list...\n", i);
    }
    printf("\n");
    
    //遍历链表中删除大于15的数据
    i = 0;
    JH_STATIC_LIST_FOR_EACH_ENTRY_ELEMENT_SAFE(cursor, next_cursor, list_buf, p_value, data)
    {
        printf("Node %d's data: %d\n", i, *p_value);
        if(*p_value > 15)
            jh_static_list_delete_and_free(list_buf, cursor);
        
        i++;
    }
    printf("\n");
    
    //遍历检查下链表
    i = 0;
    JH_STATIC_LIST_FOR_EACH_ENTRY_ELEMENT(cursor, list_buf, p_value, data)
    {
        printf("Node %d's data: %d\n", i, *p_value);
        i++;
    }
    printf("\n");
}

//遍历链表中添加特定数据
void static_list_for_each_add_test(void)
{
    int i;
    int cursor;
    int next_cursor;
    itemtype value;
    itemtype *p_value;
    
    //定义链表
    jh_static_list_buf list_buf;
    
    //初始化
    jh_static_list_buf_init(list_buf);
    
    printf("********************************\n");
    printf("遍历链表中添加特定数据\n");
    printf("********************************\n");
    //放入数值
    for (i = 0; i < 10; i++)
    {
        value = i + 10;
        //往链表尾添加数据
        JH_STATIC_LIST_ADD_TAIL_TYPE(list_buf, data, value);
        printf("Node %d has added to the list...\n", i);
    }
    printf("\n");
    
    //遍历链表中在数值为15的结点后添加一个值为25的结点
    i = 0;
    JH_STATIC_LIST_FOR_EACH_ENTRY_ELEMENT_SAFE(cursor, next_cursor, list_buf, p_value, data)
    {
        printf("Node %d's data: %d\n", i, *p_value);
        if(*p_value == 15) {
            value = 25;
            //添加数据
            JH_STATIC_LIST_ADD_TARGET_TYPE(list_buf, cursor, data, value);
        }
        
        i++;
    }
    printf("\n");
    
    //遍历检查下链表
    i = 0;
    JH_STATIC_LIST_FOR_EACH_ENTRY_ELEMENT(cursor, list_buf, p_value, data)
    {
        printf("Node %d's data: %d\n", i, *p_value);
        i++;
    }
    printf("\n");
}

//将链表中头结点和尾结点的数据移动到链表中间特定位置上
void static_list_get_head_tail_move_test(void)
{
    int i;
    int cursor, next_cursor, headcursor, tailcursor;
    itemtype value;
    itemtype *p_value;
    
    //定义链表
    jh_static_list_buf list_buf;
    
    //初始化
    jh_static_list_buf_init(list_buf);
    
    printf("********************************\n");
    printf("将链表中头结点和尾结点的数据移动到链表中间特定位置上\n");
    printf("********************************\n");
    //放入数值
    for (i = 0; i < 10; i++)
    {
        value = i + 10;
        //往链表尾添加数据
        JH_STATIC_LIST_ADD_TAIL_TYPE(list_buf, data, value);
        printf("Node %d has added to the list...\n", i);
    }
    printf("\n");
    
    //从链表中删除并返回头结点的游标，并判断游标是否有效
    headcursor = jh_static_list_get_and_remove_head_cursor(list_buf);
    printf("Node HEAD has %d %s\n", list_buf[headcursor].data, jh_static_list_cursor_is_vaild(headcursor) ? "vaild" : "invalid");
    
    //从链表中删除并返回尾结点的游标，并判断游标是否有效
    tailcursor = jh_static_list_get_and_remove_tail_cursor(list_buf);
    printf("Node TAIL has %d %s\n", list_buf[tailcursor].data, jh_static_list_cursor_is_vaild(tailcursor) ? "vaild" : "invalid");
    
    //将刚才的游标加入到链表中间
    i = 0;
    JH_STATIC_LIST_FOR_EACH_ENTRY_ELEMENT_SAFE(cursor, next_cursor, list_buf, p_value, data)
    {
        printf("Node %d's data: %d\n", i, *p_value);
        if(*p_value == 15) {
            //将刚才的游标加入到链表中间
            jh_static_list_add(list_buf, cursor, headcursor);
        }
        
        if(*p_value == 16) {
            //将刚才的游标加入到链表中间
            jh_static_list_add(list_buf, cursor, tailcursor);
        }
        
        i++;
    }
    printf("\n");
    
    //遍历检查下链表
    i = 0;
    JH_STATIC_LIST_FOR_EACH_ENTRY_ELEMENT(cursor, list_buf, p_value, data)
    {
        printf("Node %d's data: %d\n", i, *p_value);
        i++;
    }
    printf("\n");
}

//移动链表中数据位置
void static_list_move_test(void)
{
    int i;
    int cursor, next_cursor, target_cursor;
    itemtype value;
    itemtype *p_value;
    
    //定义链表
    jh_static_list_buf list_buf;
    
    //初始化
    jh_static_list_buf_init(list_buf);
    
    printf("********************************\n");
    printf("移动链表中数据位置\n");
    printf("********************************\n");
    //放入数值
    for (i = 0; i < 10; i++)
    {
        value = i + 10;
        //往链表尾添加数据
        JH_STATIC_LIST_ADD_TAIL_TYPE(list_buf, data, value);
        printf("Node %d has added to the list...\n", i);
    }
    printf("\n");
    
    //将刚才的游标加入到链表中间
    i = 0;
    JH_STATIC_LIST_FOR_EACH_ENTRY_ELEMENT_SAFE(cursor, next_cursor, list_buf, p_value, data)
    {
        printf("Node %d's data: %d\n", i, *p_value);
        if(*p_value == 12) {
            //数值为12的游标从链表中间删除
            jh_static_list_delete(list_buf, cursor);
            target_cursor = cursor;
        }
        
        if(*p_value == 16) {
            //将刚才的游标加入到链表中间
            jh_static_list_add(list_buf, cursor, target_cursor);
        }
        
        i++;
    }
    printf("\n");
    
    //遍历检查下链表
    i = 0;
    JH_STATIC_LIST_FOR_EACH_ENTRY_ELEMENT(cursor, list_buf, p_value, data)
    {
        printf("Node %d's data: %d\n", i, *p_value);
        i++;
    }
    printf("\n");
}

//链表空间用尽测试
void static_list_full_test(void)
{
    int i;
    int cursor;
    itemtype value;
    
    //定义链表
    jh_static_list_buf list_buf;
    
    //初始化
    jh_static_list_buf_init(list_buf);
    
    printf("********************************\n");
    printf("链表空间用尽\n");
    printf("********************************\n");
    //放入数值
    for (i = 0; i < 64; i++)
    {
        value = i;
        //往链表尾添加数据，并判断游标是否有效
        cursor = JH_STATIC_LIST_ADD_TAIL_TYPE(list_buf, data, value);
        printf("Node %d has add %d %s\n", i, value, jh_static_list_cursor_is_vaild(cursor) ? "vaild" : "invalid");
        
        //判断链表是否用尽
        printf("list %s full\n", jh_static_list_is_full(list_buf) ? "is" : "isn't");
        printf("\n");
    }
    printf("\n");
}
/************************************************************************/
/*                                                                      */
/************************************************************************/
int main(int argc, char* argv[])
{
    //遍历链表
    static_list_for_each_test();
    
    //反向遍历链表
    static_list_for_each_reverse_test();
    
    //往链表尾添加与删除数据
    static_list_add_and_delete_tail_test();
    
    //往链表头添加与删除数据
    static_list_add_and_delete_head_test();
    
    //获取链表头的数据并删除释放结点
    static_list_safe_delete_head_test();
    
    //获取链表尾的数据并删除释放结点
    static_list_safe_delete_tail_test();
    
    //查看链表头和尾的数据
    static_list_peek_test();
    
    //清空所有数据
    static_list_clear_test();
    
    //遍历链表中删除特定数据
    static_list_for_each_delete_test();
    
    //遍历链表中添加特定数据
    static_list_for_each_add_test();
    
    //将链表中头结点和尾结点的数据移动到链表中间特定位置上
    static_list_get_head_tail_move_test();
    
    //移动链表中数据位置
    static_list_move_test();
    
    //链表空间用尽
    static_list_full_test();
    
    return 0;
}